# CPack Example: User-selectable Installation Components
#
# In this example, we have a simple library (mylib) with an example
# application (mylibapp). We create a binary installer (a CPack Generator)
# which supports CPack components.

cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
project(CPackComponentsDEB VERSION 1.0.3)

# Use GNUInstallDirs in order to enforce lib64 if needed
include(GNUInstallDirs)

# Create the mylib library
add_library(mylib mylib.cpp)

# Create the mylibapp application
add_executable(mylibapp mylibapp.cpp)
target_link_libraries(mylibapp mylib)

# Duplicate of mylibapp application
# which won't be put in any component (?mistake?)
add_executable(mylibapp2 mylibapp.cpp)
target_link_libraries(mylibapp2 mylib)

if (CPackDEBConfiguration MATCHES "shlibdeps-with-private-lib")
  add_subdirectory("shlibdeps-with-private-lib")
  add_executable(mylibapp3 mylibapp.cpp)
  target_compile_definitions(mylibapp3 PRIVATE -DSHLIBDEPS_PRIVATE)
  target_link_libraries(mylibapp3 myprivatelib)
endif()

# Create installation targets. Note that we put each kind of file
# into a different component via COMPONENT. These components will
# be used to create the installation components.
install(TARGETS mylib
  ARCHIVE
  DESTINATION ${CMAKE_INSTALL_LIBDIR}
  COMPONENT libraries)

install(TARGETS mylibapp
  RUNTIME
  DESTINATION bin
  COMPONENT applications)

install(FILES mylib.h
        DESTINATION include
        COMPONENT headers)

if (CPackDEBConfiguration MATCHES "shlibdeps-with-private-lib")
  install(TARGETS mylibapp3
    RUNTIME
    DESTINATION bin
    COMPONENT applications)
endif()

# CPack boilerplate for this project
set(CPACK_PACKAGE_NAME "MyLib")
set(CPACK_PACKAGE_CONTACT "None")
set(CPACK_PACKAGE_VENDOR "CMake.org")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "MyLib - CPack Component Installation Example")
set(CPACK_PACKAGE_INSTALL_DIRECTORY "CPack Component Example")
set(CPACK_RESOURCE_FILE_LICENSE ${CMAKE_CURRENT_SOURCE_DIR}/license.txt)

# Tell CPack all of the components to install. The "ALL"
# refers to the fact that this is the set of components that
# will be included when CPack is instructed to put everything
# into the binary installer (the default behavior).
set(CPACK_COMPONENTS_ALL applications libraries headers)

# Set the displayed names for each of the components to install.
# These will be displayed in the list of components inside the installer.
set(CPACK_COMPONENT_APPLICATIONS_DISPLAY_NAME   "MyLib Application")
set(CPACK_COMPONENT_LIBRARIES_DISPLAY_NAME      "Libraries")
set(CPACK_COMPONENT_HEADERS_DISPLAY_NAME        "C++ Headers")

# Provide descriptions for each of the components to install.
# When the user hovers the mouse over the name of a component,
# the description will be shown in the "Description" box in the
# installer. If no descriptions are provided, the "Description"
# box will be removed.
set(CPACK_COMPONENT_APPLICATIONS_DESCRIPTION
  "An extremely useful application that makes use of MyLib")
set(CPACK_COMPONENT_LIBRARIES_DESCRIPTION
  "Static libraries used to build programs with MyLib")
set(CPACK_COMPONENT_HEADERS_DESCRIPTION
  "C/C++ header files for use with MyLib")

# It doesn't make sense to install the headers without the libraries
# (because you could never use the headers!), so make the headers component
# depend on the libraries component.
set(CPACK_COMPONENT_HEADERS_DEPENDS libraries)

# creates preinst/prerm scripts with specific permissions. Those permissions
# (especially executable) should be in the final archive
find_program(CHMOD_PROG chmod)
if(CHMOD_PROG)
  file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/preinst "echo default_preinst")
  file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/prerm "echo default_prerm")

  # Those should have 755 permission normally. We mess it up to see if
  # CPACK_DEBIAN_APPLICATIONS_PACKAGE_CONTROL_STRICT_PERMISSION is able to fix
  # it.
  execute_process(COMMAND ${CHMOD_PROG} 640 ${CMAKE_CURRENT_BINARY_DIR}/preinst)
  execute_process(COMMAND ${CHMOD_PROG} 640 ${CMAKE_CURRENT_BINARY_DIR}/prerm)

  set(CPACK_DEBIAN_APPLICATIONS_PACKAGE_CONTROL_EXTRA
      "${CMAKE_CURRENT_BINARY_DIR}/preinst;${CMAKE_CURRENT_BINARY_DIR}/prerm")

  set(CPACK_DEBIAN_APPLICATIONS_PACKAGE_CONTROL_STRICT_PERMISSION TRUE)
endif()

# creates a symbolic link and a directory. Those should not be hashed.
# warning: relocation of the symlink is not supported (symlinks with relative
# paths)
execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink mylibapp symtest)
install(FILES ${CPackComponentsDEB_BINARY_DIR}/symtest
        DESTINATION bin
        COMPONENT applications)

if(EXISTS "./dirtest")
  execute_process(COMMAND ${CMAKE_COMMAND} -E rm -rf ./dirtest)
endif()
# NOTE: directory left empty on purpose
execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ./dirtest)
# NOTE: we should not add the trailing "/" to dirtest
install(DIRECTORY ${CPackComponentsDEB_BINARY_DIR}/dirtest
        DESTINATION bin/
        COMPONENT applications)

# We may use the CPack specific config file in order
# to tailor CPack behavior on a CPack generator specific way
# (Behavior would be different for RPM or TGZ or DEB ...)
if (NOT DEFINED CPackDEBConfiguration)
  message(FATAL_ERROR "CPackDEBConfiguration should be defined")
endif()

# Setup project specific CPack-time CPack Config file.
configure_file(${CPackComponentsDEB_SOURCE_DIR}/MyLibCPackConfig-${CPackDEBConfiguration}.cmake.in
               ${CPackComponentsDEB_BINARY_DIR}/MyLibCPackConfig-${CPackDEBConfiguration}.cmake
               @ONLY)
set(CPACK_PROJECT_CONFIG_FILE ${CPackComponentsDEB_BINARY_DIR}/MyLibCPackConfig-${CPackDEBConfiguration}.cmake)

# set CPACK_DEBIAN_FILE_NAME to use default package name format
set(CPACK_DEBIAN_FILE_NAME "DEB-DEFAULT")

# Include CPack to introduce the appropriate targets
include(CPack)
